#include <QtDebug>
#include <QVector>
#include <QSettings>
#include <QTabWidget>
#include <QByteArray>
#include <QCloseEvent>
#include <QMessageBox>
//#include <QHeaderView>
#include <QSizePolicy>
#include <QTableWidget>
#include <QProgressBar>
#include <QTableWidgetItem>
#include <QRegExpValidator>

#include <qextserialbase.h>
#include <qextserialport.h>

#include "mainwindow.h"
#include "texmetercomm.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindowClass)
{
    ui->setupUi(this);

    serialPort = new texMeterComm("COM5");

    serialPort->setBaudRate(BAUD9600);
    serialPort->setDataBits(DATA_8);
    serialPort->setFlowControl(FLOW_OFF);
    serialPort->setParity(PAR_NONE);
    serialPort->setStopBits(STOP_1);
    serialPort->setTimeout(0, 10);

    readSettings();

    setupSignals();
    setupRegisterTabs();
}

MainWindow::~MainWindow()
{
    for (int i = 0; i < 4; i++)
        delete module[i];
    delete serialPort;
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    // check for changes, see if they want to save
    bool anyTabsChanged = false;
    for (int i = 0; i < 4; i++)
        if(module[i]->contentsChanged()) { anyTabsChanged = true; break; }

    if (anyTabsChanged) {
        int ret = QMessageBox::warning(this, tr("TexEE"),
                        tr("This register setup has been modified.\n"
                           "Do you want to save your changes?"),
                        QMessageBox::Yes | QMessageBox::Default,
                        QMessageBox::No,
                        QMessageBox::Cancel | QMessageBox::Escape);
        if (ret == QMessageBox::Yes) {
            fileSave();
        } else if(ret == QMessageBox::Cancel) {
            event->ignore();
            return;
        }
    }
    if(serialPort->isOpen())
        serialPort->close();
    writeSettings();
    event->accept();
}

void MainWindow::setupSignals()
{
    // setup the signals and slots for the menu items
    connect(ui->actionLoadRegisterFile, SIGNAL(triggered()), this, SLOT(fileLoad()));
    connect(ui->actionSaveRegisterFile, SIGNAL(triggered()), this, SLOT(fileSave()));
    connect(ui->actionQuit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
}

void MainWindow::setupRegisterTabs()
{
    // setup the tabs for each register
    QStringList tabNames;
    tabNames << "Internal Module";
    for (int i = 1; i < 5; i++)
        tabNames << QString("Module %1").arg(i);

    tabWidget = new QTabWidget(this);
    for (int i = 0; i < tabNames.size(); i++) {
        module[i] = new texModuleRegisterEditor();
        tabWidget->addTab(module[i], tabNames[i]);
        module[i]->setEnabled(false);
        connect(module[i], SIGNAL(modified(bool)), this, SLOT(dataChanged()));
    }

    ui->centralWidget->setLayout(new QGridLayout);
    ui->centralWidget->layout()->addWidget(tabWidget);
}

void MainWindow::readSettings()
{
    QSettings settings("Texmate", "TexEE");
    QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
    QSize size = settings.value("size", QSize(450, 300)).toSize();

/*

    // the following directives need to be tested on non-windows systems..
    QString defaultPortName = "";
#ifdef Q_OS_WIN32
    defaultPortName = "COM1";
#elif defined(Q_OS_MAC)
    defaultPortName = "/dev/tty.serial";
#else
    defaultPortName = "/dev/ttyS0";
#endif

    settings.beginGroup("portsettings");
    serialPort->setPortName(settings.value("name", defaultPortName).toString());
//    serialPort->setBaudRate(settings.value("baud", BAUD9600).value<BaudRateType>());
//    serialPort->setDataBits(settings.value("bits", DATA_8).value<DataBitsType>());
//    serialPort->setFlowControl(settings.value("flow", FLOW_OFF).value<FlowType>());
//    serialPort->setParity(settings.value("parity", PAR_NONE).value<ParityType>());
//    serialPort->setStopBits(settings.value("stop", STOP_1).value<StopBitsType>());
//    serialPortTimeout = settings.value("timeout_sec", 1).value<ulong>();
//    serialPort->setTimeout(serialPortTimeout, 0);
    settings.endGroup();
*/

    resize(size);
    move(pos);
}

void MainWindow::writeSettings()
{
    QSettings settings("Texmate", "TexEE");
    settings.setValue("pos", pos());
    settings.setValue("size", size());

/*
    settings.beginGroup("portsettings");
    settings.setValue("baud", serialPort->baudRate());
    settings.setValue("bits", serialPort->dataBits());
    settings.setValue("flow", serialPort->flowControl());
    settings.setValue("parity", serialPort->parity());
    settings.setValue("stop", serialPort->stopBits());
    settings.setValue("timeout_sec", serialPortTimeout);
    settings.endGroup();
*/
}

void MainWindow::fileLoad()
{
}

void MainWindow::fileSave()
{
}

void MainWindow::dataChanged()
{
    setWindowModified(true);
}

bool MainWindow::readMeter()
{
    // READ COMMAND
    // SUregister*
    // will return signed integer (32bit)
    // register is specified in decimal
    // registers are from 0x7001 to 0x7400

    qDebug("Attempting to open serial port for read..");

    if(serialPort->isOpen()) {
        qDebug("Serial port already open!");
        return false;
    }

    serialPort->open(QIODevice::ReadWrite);
    if(serialPort->isOpen()) {
//        read->setEnabled(false);
//        program->setEnabled(false);
//        read->repaint();    // make sure they repaint before we do blocking i/o for now..
//        program->repaint(); // won't be necessary when threaded.
        // each module has 1024 registers, each register is 4 bytes
        // we're reading 320 registers from each (1280 bytes)
        const int totalRegisters = 320;
        const int startModule = 0;
        const int endModule = 3;
//        progress->setRange(0, totalRegisters * ((endModule - startModule) + 1));
//        progress->setValue(0);
        QByteArray sent, received;
        bool ok;
//        char buffer[20];
        for (int module = startModule; module < (endModule + 1); module++) {
            for (int data = 0; data < totalRegisters; data++) {
                sent = QString("SU%1*").arg(28673 + ((module * 1024) + data)).toAscii();
                serialPort->write( sent, sent.length() );
                received = serialPort->readLine(20);
                smartModule[module][data].i = received.toInt(&ok, 10);
                qDebug() << "Sent: " << sent << "Received: " << smartModule[module][data].i;
//                progress->setValue(((module - startModule) * totalRegisters) + data);
            }
        }
//        read->setEnabled(true);
//        program->setEnabled(true);
//        progress->setValue(0);
        serialPort->close();
    } else {
        qDebug(" FAILED TO OPEN SERIAL PORT!");
    }

    return true;
}

bool MainWindow::programMeter()
{
    // WRITE COMMAND
    // SWregister,value*
    // should write signed int (32bit)

    qDebug("Attempting to open serial port for write..");

    return true;
}
